package com.xiaoq.oauth2.endpoint;

import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xiaoq.oauth2.OAuth2Constants;
import com.xiaoq.oauth2.entity.OAuth2TokenEntity;
import com.xiaoq.oauth2.service.OAuth2Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URISyntaxException;

/**
 * @author xinpeng created on 16/6/20-下午5:04. 客户端模式（client credentials）
 *         客户端模式下,不需要每个资源持有人进行登录授权,而是由API提供商直接给第三方Client进行授权,
 *         并提供access_token与refresh_token
 */
@RestController
@RequestMapping("/oauth2")
class CCTokenEndPoint {

	private static Logger logger = LoggerFactory.getLogger(CCTokenEndPoint.class);

	@Autowired
	private OAuth2Service oAuth2Service;

	private Cache cache;

	@Autowired
	public CCTokenEndPoint(CacheManager cacheManager) {
		this.cache = cacheManager.getCache("oauth2-cache");
	}

	@RequestMapping("/accessToken")
	public Object token(HttpServletRequest request) throws URISyntaxException, OAuthSystemException {
		try {
			// 构建OAuth请求
			OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);

			// 检查提交的客户端id是否正确
			if (!oAuth2Service.checkClientKey(oauthRequest.getClientId())) {
				OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
						.setError(OAuthError.TokenResponse.INVALID_CLIENT)
						.setErrorDescription(OAuth2Constants.INVALID_CLIENT_ID).buildJSONMessage();
				return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			}

			// 检查客户端安全Secret是否正确
			if (!oAuth2Service.checkClientSecret(oauthRequest.getClientId(), oauthRequest.getClientSecret())) {
				OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
						.setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
						.setErrorDescription(OAuth2Constants.INVALID_CLIENT_ID).buildJSONMessage();
				return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
			}

			// 生成Access Token
			final String accessToken = oAuth2Service.createAccessToken4clientCredentials(oauthRequest.getClientId(),
					oauthRequest.getClientSecret(), 30);
			oAuth2Service.addAccessToken(accessToken, oauthRequest.getClientId());

			String refreshToken = oAuth2Service.createRefreshToken4clientCredentials(oauthRequest.getClientId(),
					oauthRequest.getClientSecret(), 180);

			cache.put(refreshToken, accessToken);
			logger.info("accessToken : " + accessToken + "  refreshToken: " + refreshToken);

			String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
			logger.info(" redirectURI = " + redirectURI);
			// 构建oauth2授权返回信息

			OAuth2TokenEntity oAuth2_TokenEntity = new OAuth2TokenEntity();
			oAuth2_TokenEntity.setAccessToken(accessToken);
			oAuth2_TokenEntity.setRefreshToken(refreshToken);

			return new ResponseEntity<>(oAuth2_TokenEntity, HttpStatus.OK);

		} catch (OAuthProblemException e) {
			// 构建错误响应
			OAuthResponse res = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).error(e)
					.buildJSONMessage();
			return new ResponseEntity<>(res.getBody(), HttpStatus.valueOf(res.getResponseStatus()));
		}
	}
}
